package edu.ntnu.superrss.models;

import com.sun.syndication.feed.synd.SyndFeed;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.persistence.*;
import org.hibernate.annotations.Cascade;

/**
 * POJO with Hibernate annotations.
 * @author Haakon Roekenes <hakondro at stud.ntnu.no>
 */
@Entity
@Table(name = "USERS")
public class User implements Serializable {

    private String username;
    private Set<SyndFeed> feeds = new TreeSet<SyndFeed>();
    private Set<Category> categories = new TreeSet<Category>();
    private List<SyndEntryImpl> entriesRead = new ArrayList<SyndEntryImpl>();
    private List<SyndEntryImpl> entriesThumbed = new ArrayList<SyndEntryImpl>();

    public User() {
    }

    public User(String username) {
        this.username = username;
    }

    @Id
    @Column(name = "USERNAME")
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

//    @Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @ManyToMany(targetEntity = SyndFeedImpl.class, fetch=FetchType.EAGER)
    public Set getFeeds() {
        return this.feeds;
    }

    public void setFeeds(Set<SyndFeed> feeds) {
        this.feeds = feeds;
    }

    public void addFeed(SyndFeed feed) {
        feeds.add(feed);
    }

    @OneToMany(targetEntity = Category.class, fetch=FetchType.EAGER)
    public Set<Category> getCategories() {
        return this.categories;
    }

    public void setCategories(Set<Category> categories) {
        this.categories = categories;
    }

    public void addCategory(Category category) {
        this.categories.add(category);
    }

    @ManyToMany(fetch=FetchType.LAZY, targetEntity = SyndEntryImpl.class)
    public List<SyndEntryImpl> getEntriesRead() {
        return this.entriesRead;
    }

    public void setEntriesRead(List<SyndEntryImpl> entries) {
        this.entriesRead = entries;
    }

    public void addEntryRead(SyndEntryImpl entry) {
        this.entriesRead.add(entry);
    }

    @ManyToMany(fetch=FetchType.LAZY, targetEntity = SyndEntryImpl.class, cascade = CascadeType.ALL)
    @JoinTable(name="entriesThumbed", joinColumns=@JoinColumn(name="username"), inverseJoinColumns=@JoinColumn(name="entryID"))
    public List<SyndEntryImpl> getEntriesThumbed() {
        return entriesThumbed;
    }

    public void setEntriesThumbed(List<SyndEntryImpl> entriesThumbed) {
        this.entriesThumbed = entriesThumbed;
    }

    /**
     * Adds an entry as thumbed up
     * <p>
     * This method adds an entry to a users list of entriesThumbed
     * This is indicates that the user has thumbed the entry, thus cannot thumb it up once more
     *
     * If the entry is not already thumbed up by the user, the method will increment an Long variable entriesThumbed in the SyndEntryImpl object
     * If the entry is already thumbed up by the user, the method will remove the thumb up. This will also decrement the Long variable entriesThumbed in the SyndEntryImpl object
     *
     *
     * @param  SyndEntryImpl entry the SyndEntryImpl object to be marked as read
     */
    public void addEntryThumbed(SyndEntryImpl entry) {
        if (!entriesThumbed.contains(entry)) {
            this.entriesThumbed.add(entry);
            entry.incrementThumbsUp();
        } else {
            entriesThumbed.remove(entry);
            entry.decrementThumbsUp();
        }
    }

    public void removeFeed(SyndFeed sf){
        feeds.remove(sf);
    }

    public SyndFeed getFeed(Long id){
        for (SyndFeed sf : feeds){
            if(((SyndFeedImpl)sf).getId().equals(id)){
                return sf;
            }
        }
        return null;
    }

    public void removeCategory(Category category){
        this.categories.remove(category);
    }

    public Category getCategory(Long id){
        for (Category category : this.categories){
            if(category.getId().equals(id)){
                return category;
            }
        }
        return null;
    }
}
